import {Page, PAGE_START, Pageable, Slice} from "../utils/Page";
import ArrayUtils from "@zxy-cn/array-utils";
import {makeAutoObservable} from "mobx";

export interface ListDetailPageStackPaginationStoreOptions {
    pageable?: Pageable
}

/**
 * 管理分页列表和详情页状态
 */
export class ListDetailPageStackSlicinationStore<Item, Detail, Key> {
    pageable: Pageable
    last: boolean
    list: Item[] = []
    detail?: Detail

    private readonly detailToItem: (detail: Detail) => Item
    private readonly defaultPageable: Pageable
    private readonly getItemKey: (item: Item) => Key
    private readonly getDetailKey: (detail: Detail) => Key
    onRemove?:(key:Key,list:Item[])=>void

    constructor(detailToItem: (detail: Detail) => Item,
                getItemKey: (item: Item) => Key,
                getDetailKey: (detail: Detail) => Key,
                options?: ListDetailPageStackPaginationStoreOptions,
                ) {
        makeAutoObservable(this)
        this.defaultPageable = options?.pageable ?? new Pageable(PAGE_START,20)
        this.pageable = this.defaultPageable
        this.detailToItem = detailToItem
        this.getItemKey = getItemKey
        this.getDetailKey = getDetailKey
    }

    next(){
        this.pageable = this.pageable.next
    }

    appendItems(page: Slice<Item>) {
        this.list = this.list.concat(page.content).filter((value, index, array)=>{
            return array.findIndex(el=>this.getItemKey(el)===this.getItemKey(value))===index
        })
        this.last = page.last
    }

    appendItemByDetail(detail:Detail){
        this.detail = detail
        const item = this.detailToItem(detail)
        this.list = this.list.concat(item)
    }

    clearList() {
        this.list = []
        this.last = false
        this.pageable = this.pageable.first
    }

    resetListAndPageable(){
        this.list = []
        this.last = false
        this.pageable = this.defaultPageable
    }

    resetListAndPageableAndAppendPage(page:Page<Item>){
        this.list = []
        this.last = false
        this.pageable = this.defaultPageable
        this.appendItems(page)
    }

    setDetail(detail?: Detail) {
        this.detail = detail
    }

    updateDetail(detail:Detail){
        let list = Array.from(this.list);
        let index = this.list.findIndex(item => this.getItemKey(item) === this.getDetailKey(detail));
        list[index] = this.detailToItem(detail)
        this.list = list
    }

    async removeItemByKey(itemKey:Key){
        if (this.detail && this.getDetailKey(this.detail)===itemKey){
            this.setDetail(undefined)
        }
        let list = Array.from(this.list);
        if (ArrayUtils.removeBy(list,item=>this.getItemKey(item)===itemKey)){
            this.list = list
            if (this.onRemove){
                this.onRemove(itemKey,list)
            }
        }
    }


}